<html>
<head>
  <script src="../../lib/OpenLayers.js"></script>
  <script type="text/javascript">

    function test_constructor(t) {
        t.plan(4);
        var options = {'foo': 'bar'};
        var format  = new OpenLayers.Format.QueryStringFilter(options);
        t.ok(format instanceof OpenLayers.Format.QueryStringFilter,
           "new OpenLayers.Format.QueryStringFilter object");
        t.eq(format.foo, "bar", "constructor sets options correctly")
        t.eq(typeof format.write, 'function', 'format has a write function');
        t.eq(format.options, options, "format.options correctly set");
    }

    function test_write(t) {
        t.plan(30);

        // setup

        var format, filter, params;

        format = new OpenLayers.Format.QueryStringFilter();

        // 1 test
        filter = new OpenLayers.Filter.Spatial({
            type: OpenLayers.Filter.Spatial.BBOX,
            value: new OpenLayers.Bounds(0, 1, 2, 3)
        });
        params = format.write(filter);
        t.eq(params.bbox, [0, 1, 2, 3], "correct bbox param if passed a BBOX filter");

        // 3 tests
        var lon = 100, lat = 200, tolerance = 10;
        filter = new OpenLayers.Filter.Spatial({
            type: OpenLayers.Filter.Spatial.DWITHIN,
            value: new OpenLayers.Geometry.Point(lon, lat),
            distance: tolerance
        });
        params = format.write(filter);
        t.eq(params.lon, lon, "correct lon param if passed a DWITHIN filter");
        t.eq(params.lat, lat, "correct lat param if passed a DWITHIN filter");
        t.eq(params.tolerance, tolerance, "correct tolerance param if passed a DWITHIN filter");

        // 2 tests
        filter = new OpenLayers.Filter.Spatial({
            type: OpenLayers.Filter.Spatial.WITHIN,
            value: new OpenLayers.Geometry.Point(lon, lat)
        });
        params = format.write(filter);
        t.eq(params.lon, lon, "correct lon param if passed a WITHIN filter");
        t.eq(params.lat, lat, "correct lat param if passed a WITHIN filter");

        // Some bbox filters used in the next tests.

        var bboxFilter1 = new OpenLayers.Filter.Spatial({
            type: OpenLayers.Filter.Spatial.BBOX,
            value:  new OpenLayers.Bounds(0, 0, 10, 10)
        });

        var bboxFilter2 = new OpenLayers.Filter.Spatial({
            type: OpenLayers.Filter.Spatial.BBOX,
            value:  new OpenLayers.Bounds(0, 0, 20, 20)
        });

        // 1 test
        filter = new OpenLayers.Filter.Logical({
            type: OpenLayers.Filter.Logical.AND,
            filters: []
        });
        params = format.write(filter);
        t.eq(params, {}, "returns empty object if given empty AND Logical filter");

        // 1 test
        filter = new OpenLayers.Filter.Logical({
            type: OpenLayers.Filter.Logical.OR,
            filters: [
                bboxFilter1
            ]
        });
        params = format.write(filter);
        t.eq(params, {}, "does not support OR Logical filter");

        // 1 test
        filter = new OpenLayers.Filter.Logical({
            type: OpenLayers.Filter.Logical.AND,
            filters: [
                bboxFilter1
            ]
        });
        params = format.write(filter);
        t.eq(params.bbox, [0, 0, 10, 10],
             "correct bbox param if passed a Logical filter containing a BBOX");

        // 1 test
        filter = new OpenLayers.Filter.Logical({
            type: OpenLayers.Filter.Logical.AND,
            filters: [
                bboxFilter1, bboxFilter2
            ]
        });
        params = format.write(filter);
        t.eq(params.bbox, [0, 0, 20, 20],
             "correct bbox param if passed multiple BBOX filter in a Logical filter");

        // 2 tests
        filter = new OpenLayers.Filter.Comparison({
            type: OpenLayers.Filter.Comparison.EQUAL_TO,
            property: "foo",
            value: "bar"
        });
        params = format.write(filter);
        t.eq(params.queryable[0], "foo",
             "correct queryable param if passed an EQUAL_TO filter");
        t.eq(params["foo__eq"], "bar",
             "correct param key and value if passed an EQUAL_TO filter");

        // 2 tests
        filter = new OpenLayers.Filter.Comparison({
            type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO,
            property: "foo",
            value: "bar"
        });
        params = format.write(filter);
        t.eq(params.queryable[0], "foo",
             "correct queryable param if passed an NOT_EQUAL_TO filter");
        t.eq(params["foo__ne"], "bar",
             "correct param key and value if passed an NOT_EQUAL_TO filter");

        // 2 tests
        filter = new OpenLayers.Filter.Comparison({
            type: OpenLayers.Filter.Comparison.LESS_THAN,
            property: "foo",
            value: "bar"
        });
        var params = format.write(filter);
        t.eq(params.queryable[0], "foo",
             "correct queryable param if passed an LESS_THAN filter");
        t.eq(params["foo__lt"], "bar",
             "correct param key and value if passed an LESS_THAN filter");

        // 2 tests
        filter = new OpenLayers.Filter.Comparison({
            type: OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO,
            property: "foo",
            value: "bar"
        });
        var params = format.write(filter);
        t.eq(params.queryable[0], "foo",
             "correct queryable param if passed an LESS_THAN_OR_EQUAL_TO filter");
        t.eq(params["foo__lte"], "bar",
             "correct param key and value if passed an LESS_THAN_OR_EQUAL_TO filter");

        // 2 tests
        filter = new OpenLayers.Filter.Comparison({
            type: OpenLayers.Filter.Comparison.GREATER_THAN,
            property: "foo",
            value: "bar"
        });
        params = format.write(filter);
        t.eq(params.queryable[0], "foo",
             "correct queryable param if passed an GREATER_THAN filter");
        t.eq(params["foo__gt"], "bar",
             "correct param key and value if passed an GREATER_THAN filter");

        // 2 tests
        filter = new OpenLayers.Filter.Comparison({
            type: OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO,
            property: "foo",
            value: "bar"
        });
        params = format.write(filter);
        t.eq(params.queryable[0], "foo",
             "correct queryable param if passed an GREATER_THAN_OR_EQUAL_TO filter");
        t.eq(params["foo__gte"], "bar",
             "correct param key and value if passed an GREATER_THAN_OR_EQUAL_TO filter");

        // 2 tests
        filter = new OpenLayers.Filter.Comparison({
            type: OpenLayers.Filter.Comparison.LIKE,
            property: "foo",
            value: "bar"
        });
        params = format.write(filter);
        t.eq(params.queryable[0], "foo",
             "correct queryable param if passed a LIKE filter");
        t.eq(params["foo__ilike"], "bar",
             "correct param key and value if passed an LIKE filter");

        // 4 tests
        filter = new OpenLayers.Filter.Logical({
            type: OpenLayers.Filter.Logical.AND,
            filters: [
                new OpenLayers.Filter.Comparison({
                    type: OpenLayers.Filter.Comparison.EQUAL_TO,
                    property: "foo",
                    value: "bar"
                }),
                new OpenLayers.Filter.Comparison({
                    type: OpenLayers.Filter.Comparison.LESS_THAN,
                    property: "foo2",
                    value: "baz"
                })
            ]
        });
        params = format.write(filter);
        t.eq(params.queryable[0], "foo",
             "correct queryable param if passed an EQUAL_TO filter within a AND filter");
        t.eq(params["foo__eq"], "bar",
             "correct param key and value if passed an EQUAL_TO filter within a AND filter");
        t.eq(params.queryable[1], "foo2",
             "correct queryable param if passed a LESS_THAN filter within a AND filter");
        t.eq(params["foo2__lt"], "baz",
             "correct param key and value if passed a LESS_THAN filter within a AND filter");

        // 2 tests
        format = new OpenLayers.Format.QueryStringFilter({wildcarded: true});
        filter = new OpenLayers.Filter.Comparison({
            type: OpenLayers.Filter.Comparison.LIKE,
            property: "foo",
            value: "bar"
        });
        params = format.write(filter);
        t.eq(params.queryable[0], "foo",
             "correct queryable param if passed a LIKE filter (wildcarded true)");
        t.eq(params["foo__ilike"], "%bar%",
             "correct param key and value if passed an LIKE filter (wildcarded true)");
    }

    function test_regex2value(t) {
        t.plan(16);

        // setup

        var format = new OpenLayers.Format.QueryStringFilter();

        var value;
        var filter = new OpenLayers.Filter.Comparison({
            type: OpenLayers.Filter.Comparison.LIKE,
            property: "prop"
        });
        
        function serialize(value) {
            filter.value = value;
            return format.write(filter).prop__ilike;
        }

        // test

        value = serialize("foo");
        t.eq(value, "foo", 'regex2value converts "foo" to "foo"');

        value = serialize("foo%");
        t.eq(value, "foo\\%", 'regex2value converts "foo%" to "foo\\%"');

        value = serialize("foo.*");
        t.eq(value, "foo%", 'regex2value converts "foo.*" to "foo%"');

        value = serialize("f.*oo.*");
        t.eq(value, "f%oo%", 'regex2value converts "f.*oo.*" to "f%oo%"');

        value = serialize("foo.");
        t.eq(value, "foo_", 'regex2value converts "foo." to "foo_"');

        value = serialize("f.oo.");
        t.eq(value, "f_oo_", 'regex2value converts "f.oo." to "f_oo_"');

        value = serialize("f.oo.*");
        t.eq(value, "f_oo%", 'regex2value converts "f.oo.*" to "f_oo%"');

        value = serialize("foo\\\\");
        t.eq(value, "foo\\\\", 'regex2value converts "foo\\\\" to "foo\\\\"');

        value = serialize("foo\\.");
        t.eq(value, "foo.", 'regex2value converts "foo\\." to "foo."');

        value = serialize("foo\\\\.");
        t.eq(value, "foo\\\\_", 'regex2value converts "foo\\\\." to "foo\\\\_"');

        value = serialize("foo\\*");
        t.eq(value, "foo*", 'regex2value converts "foo\\*" to "foo*"');

        value = serialize("foo\\\\*");
        t.eq(value, "foo\\\\*", 'regex2value converts "foo\\\\*" to "foo\\\\*"');

        value = serialize("foo\\\\.*");
        t.eq(value, "foo\\\\%", 'regex2value converts "foo\\\\.*" to "foo\\\\%"');

        value = serialize("fo\\.o.*");
        t.eq(value, "fo.o%", 'regex2value converts from "fo\\.o.*" to "fo.o%"');

        value = serialize("fo.*o\\.");
        t.eq(value, "fo%o.", 'regex2value converts from "fo.*o\\." to "to%o."');

        value = serialize("\\*\\..*.\\\\.*\\\\.%");
        t.eq(value, "*.%_\\\\%\\\\_\\%",
             'regex2value converts from "\\*\\..*.\\\\.*\\\\.%" ' +
             'to "*.%_\\\\%\\\\_\\%"');
    }

  </script>
</head>
<body>
</body>
</html>
